/* ***********************************************************************
 * Copyright (C) 1992-2013 中国南方航空股份有限公司.
 *
 * Created [2013-3-27 下午3:48:47] by FMS Team
 * ***********************************************************************
 *
 * ClassloaderDemo
 * ***********************************************************************
 */
package com.fare.taluo.core.domain.crawl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;

/**
 * <p>com.foreveross.loader.CustomCL.java</p>
 *
 * @author deng(mail)
 * @version $Revision$ $Date$
 * @modifyed by deng(mail) description
 * @purpose 自己实现的加载器
 */
public class HotswapCL extends ClassLoader{

	 /**
	  *  需要该类加载器直接加载的类文件的基目录
	  */
	private String basedir;
	/**
	 *  需要由该类加载器直接加载的类名
	 */
    private HashSet dynaclazns; 

    /**
     * 
      * 创建一个新的实例 
      * 根据目录与类名数组，从本地磁盘上动态装载类，然后动态调用
      * 
      * @param basedir  存储类的磁盘路径
      * @param clazns 	类名数组
     */
    public HotswapCL(String basedir, String[] clazns) { 
        super(null); // 指定父类加载器为 null 
        this.basedir = basedir; 
        dynaclazns = new HashSet(); 
        loadClassByMe(clazns); 
    } 

    /**
     * 
      * loadClassByMe(这里用一句话描述这个方法的作用)
      * @param clazns 
     */
    private void loadClassByMe(String[] clazns) { 
        for (int i = 0; i < clazns.length; i++) { 
        	//将类实例化并加入到classloader中，则外部才可进行调用
            loadDirectly(clazns[i]); 
            dynaclazns.add(clazns[i]); 
        } 
    } 

    /**
     * 
      * 根据文件名称加载一个类
      * @param name 
      * @return Class 
     */
    private Class loadDirectly(String name) { 
        Class cls = null; 
        StringBuffer sb = new StringBuffer(basedir); 
        String classname = name.replace('.', File.separatorChar) + ".class";
        sb.append(File.separator + classname);
        File classF = new File(sb.toString()); 
        try {
			cls = instantiateClass(name,new FileInputStream(classF),
			    classF.length());
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
        return cls; 
    }   		

    /**
     * 读取文件流，转换byte数组
     * @param name
     * @param fin
     * @param len
     * @return
     */
    private Class instantiateClass(String name,InputStream fin,long len){ 
        byte[] raw = new byte[(int) len]; 
        try {
			fin.read(raw);
			fin.close(); 
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
        //通过这个方法，根据名称，byte数组，长度，返回一个class
        return defineClass(name,raw,0,raw.length); 
    } 
    
    /**
     * 在当前的classloader中根据名称查找，该类是否实例了。
     */
	protected Class loadClass(String name, boolean resolve) 
            throws ClassNotFoundException { 
        Class cls = null; 
        cls = findLoadedClass(name); 
        if(!this.dynaclazns.contains(name) && cls == null) {
            cls = getSystemClassLoader().loadClass(name); 
        }
        if (cls == null){ 
            throw new ClassNotFoundException(name); 
        }
        if (resolve) {
            resolveClass(cls); 
        }
        return cls; 
    } 
	
}

